/// <summary>
        /// Start Cluster Analysis
        /// </summary>
        /// <remarks>
        /// This abstraction get Invoked when User calls the rest API to Start Analysis.
        /// </remarks>
        /// <param name="configuration">The start configuration</param>
        /// <param name="token"></param>
        /// <returns></returns>
        public Task StartClusterAnalysisAsync(ClusterAnalysisConfiguration configuration, CancellationToken token)
        {
            ReleaseAssert.AssertIfNull(configuration, "configuration");

            // Please note - since this is a user call, the end user call parameter value is true.
            return(this.StartClusterAnalysisInternalAsync(endUserCall: true, configuration: configuration, token: token));
        }
 private Task PersistCurrentConfigurationAsync(ClusterAnalysisConfiguration configuration, CancellationToken token)
 {
     return(this.clusterAnalyzerApiStateStore.SetEntityAsync(
                ClusterAnalysisApiStateStoreLaunchConfigKey,
                JsonConvert.SerializeObject(configuration, this.serializationSettings),
                token));
 }
        private async Task StartClusterAnalysisInternalAsync(bool endUserCall, ClusterAnalysisConfiguration configuration, CancellationToken token)
        {
            await this.startStopApiSingleAccessLock.WaitAsync(token).ConfigureAwait(false);

            try
            {
                var currentState = await this.GetCurrentStatusAsync(token).ConfigureAwait(false);

                // We skip the current state check if it is "not" an end user call. This is to cover scenario like process crash
                // where internal data structure may not have been updated to reflect stopped status and the new primary calls
                // this start again. TODO: Think of better of supporting this scenario.
                if (endUserCall && currentState.CurrentState == FeatureState.Running)
                {
                    this.logger.LogMessage("Analysis is already Running. Please Call Stop and then start.");
                    throw new Exception("TODO ::: Analysis is already Running. Please Call Stop and then start");
                }

                // Create a linked token source.
                this.stopCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);

                var runtime = await this.CreateRunTimeAsync(configuration, this.stopCancellationTokenSource.Token).ConfigureAwait(false);

                this.runner = new ClusterAnalysisRunner(runtime.GetLogProvider());
                await this.runner.StartClusterAnalysisAsync(
                    runtime,
                    new List <IAnalysisConsumer> {
                    new TraceAnalysisConsumer()
                },
                    this.stopCancellationTokenSource.Token);

                // Persist the current Configuration.
                await this.PersistCurrentConfigurationAsync(configuration, token);

                // If this was called by end user, we update the user intention.
                if (endUserCall)
                {
                    currentState.UserDesiredState = FeatureState.Running;
                }

                currentState.CurrentState = FeatureState.Running;
                await this.PersisteCurrentStatusAsync(currentState, token);
            }
            catch (Exception exp)
            {
                // Currently, for Preview, We swallow the Exception. This ensures we don't crash FAS.
                this.logger.LogError("Cluster Analysis Launch Failed. Exception Encountered : {0}", exp.ToString());
            }
            finally
            {
                this.startStopApiSingleAccessLock.Release();
            }
        }
 private Config CreateOneBoxConfig(ClusterAnalysisConfiguration configuration)
 {
     return(new Config
     {
         RunMode = RunMode.OneBoxCluster,
         RuntimeContext =
             new RuntimeContext
         {
             FabricCodePath = FabricEnvironment.GetCodePath(),
             FabricDataRoot = FabricEnvironment.GetDataRoot(),
             FabricLogRoot = FabricEnvironment.GetLogRoot()
         },
         IsCrashDumpAnalysisEnabled = false,
         CrashDumpAnalyzerServiceName = string.Empty,
         NamedConfigManager = this.PopulateConfigurationManager(configuration)
     });
 }
        private async Task <IInsightRuntime> CreateRunTimeAsync(ClusterAnalysisConfiguration configuration, CancellationToken token)
        {
            this.logger.LogMessage("CreateRunTimeAsync:: Entering");

            IInsightRuntime runtime;
            var             isOneBox = await this.IsCurrentDeploymentOneboxAsync(token).ConfigureAwait(false);

            if (isOneBox)
            {
                var config = this.CreateOneBoxConfig(configuration);
                this.logger.LogMessage("OneBoxConfig: {0}", config);

                runtime = DefaultInsightRuntime.GetInstance(
                    ClusterAnalysisLogProvider.LogProvider,
                    PersistentStoreProvider.GetStateProvider(this.stateManager),
                    config,
                    new PerformanceSessionManager(ClusterAnalysisLogProvider.LogProvider, token),
                    new TaskRunner(ClusterAnalysisLogProvider.LogProvider, this.OnUnhandledExceptionInAnalysisAsync),
                    token);

                this.AddServiceToRuntime(runtime, typeof(FabricClient), this.fabricClient);
                this.AddServiceToRuntime(runtime, typeof(IClusterQuery), ClusterQuery.CreateClusterQueryInstance(runtime));
                this.AddServiceToRuntime(runtime, typeof(IResolveServiceEndpoint), new ResolveServiceEndpoint(ServicePartitionResolver.GetDefault()));

                var localStoreConnection = new LocalTraceStoreConnectionInformation(
                    runtime.GetCurrentConfig().RuntimeContext.FabricDataRoot,
                    runtime.GetCurrentConfig().RuntimeContext.FabricLogRoot,
                    runtime.GetCurrentConfig().RuntimeContext.FabricCodePath);

                this.AddServiceToRuntime(
                    runtime,
                    typeof(TraceStoreConnectionInformation),
                    localStoreConnection);
            }
            else
            {
                this.logger.LogMessage("CreateRunTimeAsync:: Only One-Box deployment supported currently");
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Cluster Analysis is only supported on One-Box deployment for Preview."));
            }

            return(runtime);
        }
        private NamedConfigManager PopulateConfigurationManager(ClusterAnalysisConfiguration configuration)
        {
            var configManagerData = configuration.AgentConfiguration.ToDictionary(oneConfig => oneConfig.AgentName, oneConfig => oneConfig.AgentContext);

            return(new NamedConfigManager(configManagerData));
        }