private void TraceFinish(BrowserCommandResult <TReturn> result)
        {
            bool success = result.Success == true;
            var  eventId = success ? Constants.Tracing.CommandStopEventId : Constants.Tracing.CommandErrorEventId;

            var attempts  = result.ExecutionAttempts;
            var time      = result.ExecutionTime;
            var strResult = success ? "Success" : "Failure";

            var value = success ?
                        result.Value?.ToString() :
                        result.Exception?.ToString();

            string message = $"Command {strResult}: {Options.CommandName}" +
                             $" - {attempts} attempts - total execution time {time}ms" +
                             $" - Return Result: {value ?? "null"}";

            Trace.TraceEvent(TraceEventType.Information, eventId, message);
        }
        //[DebuggerNonUserCode()]
        public BrowserCommandResult <TReturn> Execute <T1, T2, T3, T4, T5, T6, T7, T8, T9>(IWebDriver driver, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
        {
            int retries = this.Options.RetryAttempts;
            var result  = new BrowserCommandResult <TReturn>();

            result.CommandName = this.Options.CommandName;

            System.Diagnostics.Trace.CorrelationManager.StartLogicalOperation();

            result.Start();

            while (retries-- >= 0)
            {
                try
                {
                    result.ExecutionAttempts++;

                    Trace.TraceEvent(TraceEventType.Information,
                                     Constants.Tracing.CommandStartEventId,
                                     "Command Start: {0} - Attempt {1}/{2}",
                                     this.Options.CommandName,
                                     result.ExecutionAttempts,
                                     this.Options.RetryAttempts);

                    result.Value   = ExecuteCommand(driver, p1, p2, p3, p4, p5, p6, p7, p8, p9);
                    result.Success = true;
                }
                catch (Exception e)
                {
                    result.Success   = false;
                    result.Exception = e;

                    if (this.Options.ExceptionTypes != null && this.Options.ExceptionTypes.Count > 0)
                    {
                        var isAssignable = this.Options.ExceptionTypes
                                           .Any(t => t.IsAssignableFrom(e.GetType()));

                        if (!isAssignable || retries == 0)
                        {
                            Trace.TraceEvent(TraceEventType.Error,
                                             Constants.Tracing.CommandErrorEventId,
                                             "Command Error: {0} - Attempt {1}/{2} - {3} - {4}",
                                             this.Options.CommandName,
                                             result.ExecutionAttempts,
                                             this.Options.RetryAttempts,
                                             e.GetType().FullName, e.Message);

                            if (this.Options.ThrowExceptions)
                            {
                                throw;
                            }
                        }
                        else
                        {
                            if (this.Options.ExceptionAction != null)
                            {
                                Trace.TraceEvent(TraceEventType.Information,
                                                 Constants.Tracing.CommandRetryEventId,
                                                 "Command Error: {0} - Retry Action initiated",
                                                 this.Options.CommandName);

                                this.Options.ExceptionAction(e);
                            }

                            if (this.Options.RetryDelay > 0)
                            {
                                Thread.Sleep(this.Options.RetryDelay);
                            }
                        }
                    }
                    else
                    {
                        Trace.TraceEvent(TraceEventType.Error,
                                         Constants.Tracing.CommandErrorEventId,
                                         "Command Error: {0} - Attempt {1}/{2} - {3} - {4}",
                                         this.Options.CommandName,
                                         result.ExecutionAttempts,
                                         this.Options.RetryAttempts,
                                         e.GetType().FullName, e.Message);

                        if (this.Options.ThrowExceptions)
                        {
                            throw;
                        }
                    }
                }
                finally
                {
                    if (result.Success.HasValue && result.Success.Value)
                    {
                        retries = -1;
                    }
                }
            }

            result.Stop();

            Trace.TraceEvent(TraceEventType.Information,
                             Constants.Tracing.CommandStopEventId,
                             "Command Stop: {0} - {1} attempts - total execution time {2}ms",
                             this.Options.CommandName,
                             result.ExecutionAttempts,
                             result.ExecutionTime);

            System.Diagnostics.Trace.CorrelationManager.StopLogicalOperation();

            return(result);
        }
        //[DebuggerNonUserCode()]
        public BrowserCommandResult <TReturn> Execute <T1, T2, T3, T4, T5, T6, T7, T8, T9>(IWebDriver driver, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
        {
            int retries          = 1;
            int maxRetryAttempts = Options.RetryAttempts;
            int maxRetryAttemptsNotIgnoredExceptions = Options.RetryAttemptsNotIgnoredExceptions;

            var result = new BrowserCommandResult <TReturn> {
                CommandName = Options.CommandName
            };

            System.Diagnostics.Trace.CorrelationManager.StartLogicalOperation();

            result.Start();
            TraceExecutionStart(retries, maxRetryAttempts);
            while (true)
            {
                try
                {
                    result.Value   = ExecuteCommand(driver, p1, p2, p3, p4, p5, p6, p7, p8, p9);
                    result.Success = true;
                }
                catch (Exception e)
                {
                    bool canRetry = false;
                    if (retries < maxRetryAttempts)
                    {
                        if (retries < maxRetryAttemptsNotIgnoredExceptions)
                        {
                            canRetry = true;
                        }
                        else
                        {
                            canRetry = Options.ExceptionTypes?.Any(t => t.IsInstanceOfType(e)) ?? false;
                        }
                    }

                    if (canRetry)
                    {
                        retries++;
                        TraceExecutionRetry(e, retries, maxRetryAttempts);
                        Options.ExceptionAction?.Invoke(e);

                        if (Options.RetryDelay > 0)
                        {
                            Thread.Sleep(Options.RetryDelay);
                        }

                        continue;
                    }
                    result.Exception = e;
                    result.Success   = false;
                }
                break;
            }
            result.ExecutionAttempts = retries;
            result.Stop();
            TraceFinish(result);

            System.Diagnostics.Trace.CorrelationManager.StopLogicalOperation();

            if (result.Success == false && Options.ThrowExceptions)
            {
                throw result.Exception;
            }

            return(result);
        }