public CreateExperiment(AnalyticsAccount account, string name, bool serverSide = true, int?nodeUnderTest = null) : base(account) { if (!serverSide && nodeUnderTest < 1) { throw new InvalidOperationException("A valid node ID must be specificed for front-end tests"); } if (serverSide && nodeUnderTest.HasValue) { throw new InvalidOperationException("A server side experiment cannot specify a node ID"); } if (string.IsNullOrEmpty(name)) { if (serverSide) { throw new InvalidOperationException("Experiment name is required for server-side experiments"); } else { if (!ServerSide && string.IsNullOrEmpty(name)) { var node = UmbracoContext.Application.Services.ContentService.GetById(NodeUnderTestId); name = node.Name; } } } ServerSide = serverSide; NodeUnderTestId = nodeUnderTest ?? -1; Name = name; }
public IEnumerable <MSADLA.Models.JobInformation> JobList(AnalyticsAccount account, Microsoft.Rest.Azure.OData.ODataQuery <MSADLA.Models.JobInformation> odata_query, int top) { // Other parameters string opt_select = null; bool? opt_count = null; int item_count = 0; var page = this.RestClient.Job.List(account.Name, odata_query, opt_select, opt_count); foreach ( var job in RestUtil.EnumItemsInPages <MSADLA.Models.JobInformation>(page, p => this.RestClient.Job.ListNext(p.NextPageLink))) { yield return(job); item_count++; if ((top > 0) && (item_count >= top)) { break; } } }
public async Task <HttpResponseMessage> CheckAccess(CancellationToken cancellationToken) { var response = new List <object>(); foreach (var config in AnalyticsAccount.GetAll()) { bool hasAccess = false; bool isConnected = false; string error = string.Empty; try { isConnected = await uSplitAuthorizationCodeFlow.GetInstance(config).IsConnected(cancellationToken); if (isConnected) { hasAccess = await new CheckAccess(config).ExecuteAsync(); } } catch (Exception ex) { error = ex.Message; } response.Add(new { Name = config.Name, HasAccess = hasAccess, IsConnected = isConnected, Error = error, ProfileId = config.UniqueId, }); } return(CreateResponse(response)); }
public Account(AnalyticsAccount account) { Id = account.Id; Name = account.Name; Created = account.Created; Updated = account.Updated; }
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); var accounts = AnalyticsAccount.GetAll().ToList(); if (IsRootNode(id)) { if (accounts.Count == 1) { menu.Items.Add <ActionNew>("Create a new experiment", "profileId", accounts.First().UniqueId); } } else if (accounts.Any(x => x.UniqueId == id)) { menu.Items.Add <ActionNew>("Create a new experiment", "profileId", id); } else //experiment node { //TODO: Nice-to-haves //menu.Items.Add<ActionPublish>("Start this experiment"); //menu.Items.Add<ActionDisable>("Stop this experiment"); menu.Items.Add <ActionDelete>("Delete this experiment"); } return(menu); }
public async Task UpdateExperimentsCacheAsync() { //TODO: check if we are configured, otherwise this will generate errors every now and then var experiments = new List <GoogleExperiment>(); foreach (var config in AnalyticsAccount.GetAll()) { logger.Info(typeof(ExperimentsUpdater), $"Updating experiments data from Google Analytics for {config.Name} (ID {config.UniqueId})."); try { var result = await new GetExperiments(config).ExecuteAsync(); experiments.AddRange(result.Items); } catch (Exception ex) { logger.Error(typeof(ExperimentsUpdater), $"Failed to download A/B testing data for {config.Name} (ID {config.UniqueId}).", ex); } } try { var cache = ApplicationContext.Current.ApplicationCache.RuntimeCache; cache.InsertCacheItem(Constants.Cache.RawExperimentData, () => experiments, Constants.Cache.ExperimentsRefreshInterval); cache.ClearCacheItem(Constants.Cache.ParsedExperiments); } catch (Exception ex) { logger.Error(typeof(ExperimentsUpdater), $"Failed to update cache after downloading experiments.", ex); } }
public async Task <GoogleExperiment> CreateExperimentAsync(string profileId, string name, int?nodeId = null) { var command = new CreateExperiment(AnalyticsAccount.GetByUniqueId(profileId), name, nodeId == null, nodeId); return(await ExecuteAsync(command)); }
private static string GetStoragePath(AnalyticsAccount config) { var appName = Constants.ApplicationName; var storagePath = HostingEnvironment.MapPath($"~/App_Data/TEMP/{appName}/google/auth/{config.UniqueId}"); return(storagePath); }
public static uSplitAuthorizationCodeFlow GetInstance(AnalyticsAccount config) { if (!Instances.ContainsKey(config.UniqueId)) { Instances[config.UniqueId] = new uSplitAuthorizationCodeFlow(config); } return(Instances[config.UniqueId]); }
public async Task DeleteVariationAsync(string profileId, [FromBody] DeleteVariationRequest request) { await ExecuteAsync(new DeleteVariation(AnalyticsAccount.GetByUniqueId(profileId)) { GoogleExperimentId = request.ExperimentId, VariationName = request.VariationName }); }
public JobInfo JobBuild(AnalyticsAccount account, SubmitJobOptions options) { var job_props = options.ToJobInformationObject(); var job_info = this.RestClient.Job.Build(account.Name, job_props); var j = new JobInfo(job_info, account); return(j); }
public IEnumerable <MSADL.Analytics.Models.SasTokenInfo> ListSasTokens(AnalyticsAccount account, string storage_account, string container) { var initial_page = this.RestClient.StorageAccounts.ListSasTokens(account.ResourceGroup, account.Name, storage_account, container); foreach (var acc in RestUtil.EnumItemsInPages(initial_page, p => this.RestClient.StorageAccounts.ListSasTokensNext(p.NextPageLink))) { yield return(acc); } }
public static ManagementResource.ExperimentsResource.ListRequest List( this ManagementResource.ExperimentsResource experiments, AnalyticsAccount config) { var accountId = config.GoogleAccountId; var webPropertyId = config.GoogleWebPropertyId; var profileId = config.GoogleProfileId; return(experiments.List(accountId, webPropertyId, profileId)); }
public async Task <IHttpActionResult> SetSegmentAsync(string profileId, [FromBody] SetSegmentRequest request) { await ExecuteAsync(new SetSegment(AnalyticsAccount.GetByUniqueId(profileId)) { ExperimentId = request.ExperimentId, ProviderKey = request.ProviderKey, Value = request.Value }); return(Ok()); }
public override Task <ActionResult> IndexAsync(AuthorizationCodeResponseUrl authorizationCode, CancellationToken taskCancellationToken) { var stateWithoutRandomToken = authorizationCode.State.Substring(0, authorizationCode.State.Length - AuthorizationCodeWebApp.StateRandomLength); var uri = new Uri(stateWithoutRandomToken); var profileId = uri.ParseQueryString().Get("profileId"); var config = AnalyticsAccount.GetByUniqueId(profileId); _flowData = new uSplitFlowMetadata(config); return(base.IndexAsync(authorizationCode, taskCancellationToken)); }
public IEnumerable <MSADLA.Models.USqlTableStatistics> ListTableStatistics(AnalyticsAccount account, string dbname, string schema, string tablename) { var oDataQuery = new Microsoft.Rest.Azure.OData.ODataQuery <MSADLA.Models.USqlTableType>(); var page = this.RestClient.Catalog.ListTableStatistics(account.Name, dbname, schema, tablename); foreach (var stats in RestUtil.EnumItemsInPages <MSADLA.Models.USqlTableStatistics>(page, p => this.RestClient.Catalog.ListTableStatisticsNext(p.NextPageLink))) { yield return(stats); } }
public async Task <HttpResponseMessage> AddVariationAsync(string profileId, [FromBody] AddVariationRequest request) { var variationDetails = await ExecuteAsync(new AddVariation(AnalyticsAccount.GetByUniqueId(profileId)) { Name = request.Name, GoogleExperimentId = request.ExperimentId, NodeId = request.NodeId }); return(CreateResponse(variationDetails)); }
public async Task <HttpResponseMessage> StopExperimentAsync(string id, string profileId) { var experiment = await ExecuteAsync(new StopExperiment(AnalyticsAccount.GetByUniqueId(profileId), id)); var details = await ExecuteAsync(new GetExperimentDetails() { Experiment = experiment }); return(CreateResponse(details)); }
public IEnumerable <MSADLA.Models.USqlSchema> ListSchemas(AnalyticsAccount account, string dbname) { var oDataQuery = new Microsoft.Rest.Azure.OData.ODataQuery <MSADLA.Models.USqlSchema>(); string @select = null; bool? count = null; var page = this.RestClient.Catalog.ListSchemas(account.Name, dbname, oDataQuery, @select, count); foreach (var schema in RestUtil.EnumItemsInPages <MSADLA.Models.USqlSchema>(page, p => this.RestClient.Catalog.ListSchemasNext(p.NextPageLink))) { yield return(schema); } }
public IEnumerable <MSADLA.Models.USqlAssemblyClr> ListAssemblies(AnalyticsAccount account, string dbname) { var oDataQuery = new Microsoft.Rest.Azure.OData.ODataQuery <Microsoft.Azure.Management.DataLake.Analytics.Models.USqlAssembly>(); string @select = null; bool? count = null; var page = this.RestClient.Catalog.ListAssemblies(account.Name, dbname, oDataQuery, @select, count); foreach (var asm in RestUtil.EnumItemsInPages <MSADLA.Models.USqlAssemblyClr>(page, p => this.RestClient.Catalog.ListAssembliesNext(p.NextPageLink))) { yield return(asm); } }
private static Initializer CreateFlowInitializer(AnalyticsAccount config) { return(new Initializer { ClientSecrets = new ClientSecrets { ClientId = WebConfigurationManager.AppSettings[Constants.AppSettings.GoogleClientId], ClientSecret = WebConfigurationManager.AppSettings[Constants.AppSettings.GoogleClientSecret] }, Scopes = new[] { AnalyticsService.Scope.AnalyticsEdit }, DataStore = new FileDataStore(GetStoragePath(config), true), UserDefinedQueryParams = new [] { new KeyValuePair <string, string>("testkey", "testvalue"), }, }); }
public async Task <ActionResult> ReauthorizeAsync(string originalUrl, string profileId, CancellationToken cancellationToken) { var config = AnalyticsAccount.GetByUniqueId(profileId); var flow = uSplitAuthorizationCodeFlow.GetInstance(config); if (await flow.IsConnected(cancellationToken)) { await flow.DeleteTokenAsync(Constants.Google.SystemUserId, cancellationToken); } return(RedirectToAction(nameof(AuthorizeAsync), new { originalUrl, profileId })); }
public async Task <ActionResult> AuthorizeAsync(string originalUrl, string profileId, CancellationToken cancellationToken) { var config = AnalyticsAccount.GetByUniqueId(profileId); var result = await new AuthorizationCodeMvcApp(this, new uSplitFlowMetadata(config)).AuthorizeAsync(cancellationToken); if (result.Credential == null) { //no token, lets go to Google return(new RedirectResult(result.RedirectUri)); } //refresh the experiments cache await ExperimentsUpdater.Instance.UpdateExperimentsCacheAsync(); //got a token, we can return back return(new RedirectResult(originalUrl)); }
private TreeNode CreateAccountNode(AnalyticsAccount config, FormDataCollection queryStrings) { var name = config.Name; if (name.IsNullOrWhiteSpace()) { name = config.UniqueId; } const string icon = Constants.Icons.Account + " color-black"; var url = $"content/{Constants.Trees.AbTesting}/dashboard/{config.UniqueId}/"; var node = CreateTreeNode(config.UniqueId, $"{UmbracoConstants.System.Root}", queryStrings, name, icon, url); node.HasChildren = true; return(node); }
private async Task <TreeNodeCollection> GetNodesForAccountAsync(AnalyticsAccount config, FormDataCollection queryStrings) { var nodes = new TreeNodeCollection(); string parentId = config.UniqueId; if (!await uSplitAuthorizationCodeFlow.GetInstance(config).IsConnected(CancellationToken.None)) { nodes.Add(CreateTreeNode("error", parentId, queryStrings, "ERROR - Google API not connected", "icon-alert")); } else { nodes.AddRange(await CreateExperimentNodes(queryStrings, parentId, config)); } return(nodes); }
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { if (IsRootNode(id)) { var nodes = AsyncHelpers.RunSync(() => GetNodesUnderRootAsync(queryStrings)); return(nodes); } var accounts = AnalyticsAccount.GetAll().ToList(); var account = accounts.FirstOrDefault(x => x.UniqueId == id); if (account != null) { var nodes = AsyncHelpers.RunSync(() => GetNodesForAccountAsync(account, queryStrings)); return(nodes); } throw new NotSupportedException("Invalid node id"); }
private async Task <TreeNodeCollection> GetNodesUnderRootAsync(FormDataCollection queryStrings) { var nodes = new TreeNodeCollection(); var accounts = AnalyticsAccount.GetAll().ToList(); if (accounts.Count() > 1) { foreach (var account in accounts) { var accountNode = CreateAccountNode(account, queryStrings); nodes.Add(accountNode); } } else if (accounts.Count() == 1) { return(await GetNodesForAccountAsync(accounts[0], queryStrings)); } return(nodes); }
public async Task DeleteExperimentAsync(string id, string profileId) { var accountConfigs = AnalyticsAccount.GetAll().ToList(); AnalyticsAccount config; if ((id.IsNullOrWhiteSpace() || id == "-1") && accountConfigs.Count == 1) { config = accountConfigs.First(); } else { config = AnalyticsAccount.GetByUniqueId(profileId); } //TODO: add an option to delete variations (e.g. Umbraco content linked to it) await ExecuteAsync(new DeleteExperiment(config) { GoogleExperimentId = id }); }
internal JobInfo(MSADLA.Models.JobInformation job, AnalyticsAccount acct) { // this method is only meant to be called for JobInformation // objects that come back from list jobs or from get job if (!job.JobId.HasValue) { throw new System.ArgumentException("job's id is null"); } this.Account = acct; this.Name = job.Name; this.LogFolder = job.LogFolder; this.DegreeOfParallelism = job.DegreeOfParallelism; this.EndTime = job.EndTime; this.Id = job.JobId.Value; this.Priority = job.Priority; this.Result = job.Result; this.StartTime = job.StartTime; this.State = job.State; this.SubmitTime = job.SubmitTime; this.Type = job.Type; this.Submitter = job.Submitter; }
public CheckAccess(AnalyticsAccount config) : base(config) { }